package util

import (
	"bytes"
	"log"
	"os/exec"
)

func Ns3Sh(runDir, duration string, isDestroy bool) (out bytes.Buffer, err error) {
	cmd := exec.Command("ns3.sh", duration, "create")
	if isDestroy {
		cmd = exec.Command("ns3.sh", duration, "destroy")
	}

	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Dir = runDir
	cmd.Stderr = &out
	err = cmd.Run()
	if err != nil {
		log.Printf("exec command out: %v", stdout.String())
		log.Printf("exec command err: %v", out.String())
	}

	return
}

func StartNs3Sh(runDir, duration string, isDestroy bool) (out bytes.Buffer, err error) {
	cmd := exec.Command("ns3.sh", duration, "create")
	if isDestroy {
		cmd = exec.Command("ns3.sh", duration, "destroy")
	}

	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Dir = runDir
	cmd.Stderr = &out
	err = cmd.Start()
	if err != nil {
		log.Printf("exec command out: %v", stdout.String())
		log.Printf("exec command err: %v", out.String())
	}

	return
}

// only for pos + ns3
func StartPosNs3Sh(runDir, duration string, isDestroy bool) (out bytes.Buffer, err error) {
	cmd := exec.Command("ns3pos.sh", duration, "create")
	if isDestroy {
		cmd = exec.Command("ns3pos.sh", duration, "destroy")
	}

	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Dir = runDir
	cmd.Stderr = &out
	err = cmd.Start()
	if err != nil {
		log.Printf("exec command out: %v", stdout.String())
		log.Printf("exec command err: %v", out.String())
	}

	return
}

// docker stack deploy --compose-file docker-compose.yml vossibility
func DockerStackDeploy(yaml, stack, runDir string) (out []byte, err error) {
	cmd := exec.Command("docker", "stack", "deploy", "--compose-file", yaml, stack)
	cmd.Dir = runDir
	out, err = run(cmd)

	return
}

func DockerComposeConfigDeployUp(profile, configFile, runDir string) (out []byte, err error) {
	cmd := exec.Command("docker", "compose", "--profile", profile, "-f", configFile, "up")
	cmd.Dir = runDir
	out, err = run(cmd)

	return
}

func DockerSwarmJoinToken(manager string) (out []byte, err error) {
	if manager == "manager" {
		cmd := exec.Command("docker", "swarm", "join-token", "manager")
		out, err = run(cmd)

		return
	} else {
		cmd := exec.Command("docker", "swarm", "join-token", "worker")
		out, err = run(cmd)

		return
	}
}

func DockerComposeDeployUpConfigFile(configFile, runDir string) (out []byte, err error) {
	log.Println("docker", " compose", " -f", configFile, " up", " -d")

	cmd := exec.Command("docker", "compose", "-f", configFile, "up", "-d")
	cmd.Dir = runDir
	out, err = run(cmd)
	return
}

// docker compose --profile bootstrap up
// docker compose --profile bootstrap down
// sh -c 'docker compose --profile "bootstrap" down'
// sh -c 'docker compose --profile "bootstrap" up'
func DockerComposeDeployUp(profile, runDir string) (out []byte, err error) {
	//strForm := `docker compose --profile %s up`
	//strCmd := fmt.Sprintf(strForm, profile)
	//cmd := exec.Command("sh", "-c", strCmd)
	cmd := exec.Command("docker", "compose", "--profile", profile, "up", "-d")
	cmd.Dir = runDir
	out, err = run(cmd)

	//cmd := exec.Command("sh")
	//cmdExec := `mkdir "C:\a a"`
	//fmt.Println(fmt.Sprintf(`/c %s`, cmdExec))
	////核心点,直接修改执行命令方式
	//cmd.SysProcAttr = &syscall.SysProcAttr{CmdLine: fmt.Sprintf(`/c %s`, cmdExec), HideWindow: true}
	//output, err := cmd.Output()

	return
}

// verbose log
func DockerComposeDeployUp2(profile, runDir string) (out bytes.Buffer, err error) {
	cmd := exec.Command("docker", "compose", "--profile", profile, "up", "-d")
	var stderr bytes.Buffer
	cmd.Stdout = &out
	cmd.Dir = runDir
	cmd.Stderr = &stderr
	err = cmd.Run()
	if err != nil {
		log.Printf("exec command out: %v", out.String())
		log.Printf("exec command err: %v", stderr.String())
	}

	return
}

func DockerComposeDeployUp3(runDir string) (out bytes.Buffer, err error) {
	cmd := exec.Command("docker", "compose", "up", "-d")
	//var stderr bytes.Buffer
	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Dir = runDir
	cmd.Stderr = &out
	err = cmd.Run()
	if err != nil {
		log.Printf("exec command out: %v", stdout.String())
		log.Printf("exec command err: %v", out.String())
	}

	return
}

func DockerComposeDown1(runDir string) (out bytes.Buffer, err error) {
	cmd := exec.Command("docker", "compose", "down")
	//var stderr bytes.Buffer
	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Dir = runDir
	cmd.Stderr = &out
	err = cmd.Run()
	if err != nil {
		log.Printf("exec command out: %v", stdout.String())
		log.Printf("exec command err: %v", out.String())
	}

	return
}

func DockerStackRm(runDir, chain string) (out bytes.Buffer, err error) {
	cmd := exec.Command("docker", "stack", "rm", chain)
	//var stderr bytes.Buffer
	var stdout bytes.Buffer
	cmd.Stdout = &stdout
	cmd.Dir = runDir
	cmd.Stderr = &out
	err = cmd.Run()
	if err != nil {
		log.Printf("exec command out: %v", stdout.String())
		log.Printf("exec command err: %v", out.String())
	}

	return
}

// docker pull myregistry.example.com:5000/myimage:mytag
func DockerPullImage(image string) (out []byte, err error) {
	cmd := exec.Command("docker", "pull", image)
	out, err = run(cmd)

	return
}

func RunCmd(command string, runDir string, args ...string) (out bytes.Buffer, err error) {
	//cmd := exec.Command(command, args...)
	//cmd.Dir = runDir
	//out, err = run(cmd)
	//
	//return

	cmd := exec.Command(command, args...)
	var stderr bytes.Buffer
	cmd.Stdout = &out
	cmd.Dir = runDir
	cmd.Stderr = &stderr
	err = cmd.Run()
	if err != nil {
		log.Printf("exec command out: %v", out.String())
		log.Printf("exec command err: %v", stderr.String())
	}

	return

	//if err != nil{
	//	fmt.Println(fmt.Sprint(err)++ stderr.String())
	//	return
	//	fmt.Println("Result:"+ out.string())
}

// docker stack ls
func DockerStackLs() (out []byte, err error) {
	cmd := exec.Command("docker", "stack", "ls")
	out, err = run(cmd)

	return
}

func run(cmd *exec.Cmd) (out []byte, err error) {
	out, err = cmd.CombinedOutput()

	return
}
